package cn.xluobo.business.wechat.miniapp.base.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.xluobo.business.sys.admin.repo.model.SysUser;
import cn.xluobo.business.sys.admin.service.ISysUserService;
import cn.xluobo.business.sys.oauth.service.Oauth2Service;
import cn.xluobo.business.wechat.miniapp.base.domain.req.ReqBindUser;
import cn.xluobo.business.wechat.miniapp.base.domain.req.ReqSyncUserInfo;
import cn.xluobo.business.wechat.user.repo.model.WechatUserInfo;
import cn.xluobo.business.wechat.user.service.IWechatUserInfoService;
import cn.xluobo.config.exception.BusinessException;
import cn.xluobo.config.login.LoginUser;
import cn.xluobo.config.wechat.WxMaConfiguration;
import cn.xluobo.core.api.APIResponse;
import cn.xluobo.core.api.ApiResEnums;
import cn.xluobo.utils.LoginUserUtil;
import cn.xluobo.utils.WechatMiniAppLoginUserUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * @author ：KingLong
 * @date ：Created in 2020/10/15 09:49
 */
@Service
@Slf4j
public class WechatMiniBaseService extends Oauth2Service {

    @Autowired
    private IWechatUserInfoService wechatUserInfoService;
    @Autowired
    private ISysUserService sysUserService;

    /**
     * 根据code换取用户登录态信息
     * 根据wx.login 获取的code
     * @param appId
     * @param code
     * @return
     */
    public WxMaJscode2SessionResult getWxMaJscode2Session(String appId,String code) {
        if(StringUtils.isAnyEmpty(appId,code)) {
            return null;
        }
        final WxMaService wxService = WxMaConfiguration.getMaService(appId);
        WxMaJscode2SessionResult session;
        try {
            session = wxService.getUserService().getSessionInfo(code);
        } catch (WxErrorException e) {
            log.error("wechat get user info by code error", e);
            throw new BusinessException(e.getError().getJson());
        }
        return session;
    }

    /**
     * 同步微信用户信息
     * @return
     */
    public APIResponse syncWechatUserInfo(ReqSyncUserInfo syncUserInfo) {
        String signature = syncUserInfo.getSignature();
        String rawData = syncUserInfo.getRawData();
        String encryptedData = syncUserInfo.getEncryptedData();
        String iv = syncUserInfo.getIv();
        if(StringUtils.isAnyEmpty(signature,rawData,encryptedData,iv,syncUserInfo.getAppId())) {
            return APIResponse.toExceptionResponse(ApiResEnums.PARAM_FAIL);
        }

        // 获取用户详细信息
        final WxMaService wxService = WxMaConfiguration.getMaService(syncUserInfo.getAppId());
        WxMaJscode2SessionResult session = WechatMiniAppLoginUserUtil.getSession();
        boolean checkUserInfo = wxService.getUserService().checkUserInfo(session.getSessionKey(), rawData, signature);
        if (!checkUserInfo) {
            log.error("getWechatUserInfo user check failed");
            return APIResponse.toExceptionResponse("同步微信用户信息失败(校验失败)");
        }
        // 解密用户信息
        WxMaUserInfo wxMaUserInfo = wxService.getUserService().getUserInfo(session.getSessionKey(), encryptedData, iv);

        // db获取微信用户信息
        WechatUserInfo wechatUser = wechatUserInfoService.getWechatUser(syncUserInfo.getAppId(), wxMaUserInfo.getOpenId());
        if (null == wechatUser) {
            WechatUserInfo saveWechatUser = new WechatUserInfo();
            BeanUtils.copyProperties(wxMaUserInfo, saveWechatUser);
            saveWechatUser.setAppId(wxMaUserInfo.getWatermark().getAppid());
            wechatUserInfoService.save(saveWechatUser);
            return APIResponse.toOkResponse();
        } else {
            BeanUtils.copyProperties(wxMaUserInfo, wechatUser);
            wechatUser.setLastUpdateTime(new Date());
            wechatUserInfoService.updateById(wechatUser);
            return APIResponse.toOkResponse();
        }
    }

    /**
     * 获取微信用户信息
     * @param reqBindUser
     * @return
     */
    public APIResponse bindUser(ReqBindUser reqBindUser) {
        // 通过code获取 微信用户openId
        WxMaJscode2SessionResult session = this.getWxMaJscode2Session(reqBindUser.getAppId(), reqBindUser.getCode());
        WechatUserInfo wechatUser = wechatUserInfoService.getWechatUser(reqBindUser.getAppId(), session.getOpenid());
        if(null == wechatUser) {
            wechatUser = new WechatUserInfo();
            wechatUser.setAppId(reqBindUser.getAppId());
            wechatUser.setOpenId(session.getOpenid());
            wechatUser.setUnionId(session.getUnionid());
            wechatUser.setCreateTime(new Date());
            wechatUser.setLastUpdateTime(new Date());
            wechatUserInfoService.save(wechatUser);
        }

        // 微信用户id
        Long wechatUserId = wechatUser.getWechatUserId();

        // 账号
        String username = reqBindUser.getUsername();
        // 密码
        String password = reqBindUser.getPassword();

        // 校验用户 账号 密码
        SysUser sysUser = sysUserService.getByUserName(username);
        if(null == sysUser) {
            SysUser createSysUser = new SysUser();
            createSysUser.setPassword(password);
            createSysUser.setUsername(username);
            createSysUser.setUserType(1);
            createSysUser.setWechatUserId(wechatUserId);
            createSysUser.setCreateDate(new Date());
            sysUserService.addSysUser(createSysUser);

            return APIResponse.toOkResponse();
        }
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (bCryptPasswordEncoder.matches(password, sysUser.getPassword())) {
            // 判断该用户是否已被绑定
            Long userHadBindWechatUserId = sysUser.getWechatUserId();
            if(null != userHadBindWechatUserId) {
                WechatUserInfo bindWechatUserInfo = wechatUserInfoService.getById(userHadBindWechatUserId);
                return APIResponse.toExceptionResponse(ApiResEnums.MINI_APP_USER_HAD_BIND_BY_OTHER_USER,"该用户已被微信用户'"+bindWechatUserInfo.getNickName()+"'绑定!");
            }

            // 判断该微信用户是否绑定了其他账号
            SysUser hadBindUser = sysUserService.getByBindByWechatUserId(wechatUserId);
            if(hadBindUser != null && !hadBindUser.getUserId().equals(sysUser.getUserId())) {
                return APIResponse.toExceptionResponse(ApiResEnums.MINI_APP_WECHAT_HAD_BIND_USER,"微信账号已绑定'"+hadBindUser.getName()+"',无法绑定!");
            } else if (hadBindUser == null) {
                // 绑定
                SysUser updateSysUser = new SysUser();
                updateSysUser.setUserId(sysUser.getUserId());
                updateSysUser.setWechatUserId(wechatUserId);
                sysUserService.updateById(updateSysUser);
            }

            return APIResponse.toOkResponse();
        } else {
            return APIResponse.toExceptionResponse("账号密码错误");
        }
    }

    /**
     * 取消绑定
     * @return
     */
    public APIResponse unBindUser() {
        LoginUser loginUser = LoginUserUtil.getLoginUser();
        String userId = loginUser.getUserId();
        UpdateWrapper<SysUser> uw = new UpdateWrapper<>();
        uw.set("wechat_user_id", null);
        uw.eq("user_id", userId);
        sysUserService.update(uw);
        return APIResponse.toOkResponse();
    }
}
